[id].vue 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. <template>
  2. <div class="admin--page-content">
  3. <div class="admin--form">
  4. <table class="admin--form--table">
  5. <colgroup>
  6. <col style="width: 140px;">
  7. <col>
  8. </colgroup>
  9. <tbody>
  10. <tr>
  11. <th><div>분야</div></th>
  12. <td>{{ data.field_name || "-" }}</td>
  13. </tr>
  14. <tr>
  15. <th><div>지역</div></th>
  16. <td>{{ data.area_name || "-" }}</td>
  17. </tr>
  18. <tr>
  19. <th><div>선상명</div></th>
  20. <td class="admin--table-title">{{ data.name || "-" }}</td>
  21. </tr>
  22. <tr>
  23. <th><div>낚시지역</div></th>
  24. <td>{{ data.area_detail || "-" }}</td>
  25. </tr>
  26. <tr>
  27. <th><div>중량(톤수)</div></th>
  28. <td>{{ data.tonnage || "-" }}</td>
  29. </tr>
  30. <tr>
  31. <th><div>탑승인원</div></th>
  32. <td>{{ data.capacity || "-" }}</td>
  33. </tr>
  34. <tr>
  35. <th><div>우편번호</div></th>
  36. <td>{{ data.zip_code || "-" }}</td>
  37. </tr>
  38. <tr>
  39. <th><div>주소</div></th>
  40. <td>{{ data.address || "-" }}</td>
  41. </tr>
  42. <tr>
  43. <th><div>상세주소</div></th>
  44. <td>{{ data.address_detail || "-" }}</td>
  45. </tr>
  46. <tr>
  47. <th><div>참고항목</div></th>
  48. <td>{{ data.address_refer || "-" }}</td>
  49. </tr>
  50. <tr>
  51. <th><div>좌표</div></th>
  52. <td>
  53. <template v-if="data.lat && data.lng">{{ data.lat }}, {{ data.lng }}</template>
  54. <template v-else>-</template>
  55. </td>
  56. </tr>
  57. <tr>
  58. <th><div>제휴 여부</div></th>
  59. <td>
  60. <span :class="['admin--badge', data.partnership_YN === 'Y' ? 'admin--badge-active' : 'admin--badge-ended']">
  61. {{ data.partnership_YN === "Y" ? "제휴" : "비제휴" }}
  62. </span>
  63. </td>
  64. </tr>
  65. <tr v-if="data.partnership_YN === 'Y'">
  66. <th><div>계좌번호</div></th>
  67. <td>
  68. <template v-if="data.account_number">
  69. {{ bankName(data.bank_code) }} {{ data.account_number }}<template v-if="data.account_holder"> ({{ data.account_holder }})</template>
  70. </template>
  71. <template v-else>-</template>
  72. </td>
  73. </tr>
  74. <tr>
  75. <th><div>상태</div></th>
  76. <td>
  77. <span :class="['admin--badge', data.status_YN === 'Y' ? 'admin--badge-active' : 'admin--badge-ended']">
  78. {{ data.status_YN === "Y" ? "사용중" : "미사용" }}
  79. </span>
  80. </td>
  81. </tr>
  82. <tr>
  83. <th><div>등록일</div></th>
  84. <td>{{ formatDateTime(data.created_at) }}</td>
  85. </tr>
  86. <tr>
  87. <th><div>최근 수정</div></th>
  88. <td>{{ formatDateTime(data.updated_at) }}</td>
  89. </tr>
  90. </tbody>
  91. </table>
  92. <!-- 버튼 영역 -->
  93. <div class="admin--form-actions">
  94. <button type="button" class="admin--btn" @click="goToList">
  95. ← 목록으로
  96. </button>
  97. <button type="button" class="admin--btn admin--btn-red-border ml--auto" @click="handleDelete">
  98. 삭제
  99. </button>
  100. <button type="button" class="admin--btn admin--btn-red" @click="goToEdit">
  101. 수정
  102. </button>
  103. </div>
  104. <!-- 알림 모달 -->
  105. <AdminAlertModal
  106. v-if="alertModal.show"
  107. :title="alertModal.title"
  108. :message="alertModal.message"
  109. :type="alertModal.type"
  110. @confirm="handleAlertConfirm"
  111. @cancel="handleAlertCancel"
  112. @close="closeAlertModal"
  113. />
  114. </div>
  115. </div>
  116. </template>
  117. <script setup>
  118. import { ref, onMounted } from "vue";
  119. import { useRoute, useRouter } from "vue-router";
  120. import AdminAlertModal from "~/components/admin/AdminAlertModal.vue";
  121. definePageMeta({
  122. layout: "admin",
  123. middleware: ["auth"],
  124. });
  125. const route = useRoute();
  126. const router = useRouter();
  127. const { get, del } = useApi();
  128. const onboardId = route.params.id;
  129. const data = ref({
  130. field_name: "",
  131. area_name: "",
  132. name: "",
  133. area_detail: "",
  134. tonnage: "",
  135. capacity: "",
  136. zip_code: "",
  137. address: "",
  138. address_detail: "",
  139. address_refer: "",
  140. lat: "",
  141. lng: "",
  142. bank_code: "",
  143. account_number: "",
  144. account_holder: "",
  145. partnership_YN: "N",
  146. status_YN: "Y",
  147. created_at: "",
  148. updated_at: "",
  149. });
  150. // 은행 코드 → 은행명
  151. const bankMap = {
  152. "002": "산업은행", "003": "기업은행", "004": "국민은행", "007": "수협은행",
  153. "011": "농협은행", "020": "우리은행", "023": "SC제일은행", "031": "대구은행",
  154. "032": "부산은행", "034": "광주은행", "035": "제주은행", "037": "전북은행",
  155. "039": "경남은행", "045": "새마을금고", "071": "우체국", "081": "하나은행",
  156. "088": "신한은행", "089": "케이뱅크", "090": "카카오뱅크", "092": "토스뱅크",
  157. };
  158. const bankName = (code) => bankMap[code] || (code ? code : "-");
  159. // 알림 모달
  160. const alertModal = ref({
  161. show: false,
  162. title: "알림",
  163. message: "",
  164. type: "alert",
  165. onConfirm: null,
  166. });
  167. const showAlert = (message, title = "알림") => {
  168. alertModal.value = { show: true, title, message, type: "alert", onConfirm: null };
  169. };
  170. const showConfirm = (message, onConfirm, title = "확인") => {
  171. alertModal.value = { show: true, title, message, type: "confirm", onConfirm };
  172. };
  173. const closeAlertModal = () => { alertModal.value.show = false; };
  174. const handleAlertConfirm = () => {
  175. if (alertModal.value.onConfirm) alertModal.value.onConfirm();
  176. closeAlertModal();
  177. };
  178. const handleAlertCancel = () => closeAlertModal();
  179. // 상세 조회
  180. const loadDetail = async () => {
  181. const { data: res, error } = await get(`/onboard/${onboardId}`);
  182. if (error || !res?.success) {
  183. showAlert(error?.message || res?.message || "조회에 실패했습니다.", "오류");
  184. return;
  185. }
  186. const row = res.data || {};
  187. data.value = {
  188. field_name: row.field_name ?? "",
  189. area_name: row.area_name ?? "",
  190. name: row.name ?? "",
  191. area_detail: row.area_detail ?? "",
  192. tonnage: row.tonnage ?? "",
  193. capacity: row.capacity ?? "",
  194. zip_code: row.zip_code ?? "",
  195. address: row.address ?? "",
  196. address_detail: row.address_detail ?? "",
  197. address_refer: row.address_refer ?? "",
  198. lat: row.lat ?? "",
  199. lng: row.lng ?? "",
  200. bank_code: row.bank_code ?? "",
  201. account_number: row.account_number ?? "",
  202. account_holder: row.account_holder ?? "",
  203. partnership_YN: row.partnership_YN ?? "N",
  204. status_YN: row.status_YN ?? "Y",
  205. created_at: row.created_at ?? "",
  206. updated_at: row.updated_at ?? "",
  207. };
  208. };
  209. // 삭제
  210. const handleDelete = () => {
  211. showConfirm(
  212. `'${data.value.name}' 선상을 삭제하시겠습니까?`,
  213. async () => {
  214. const { data: res, error } = await del(`/onboard/${onboardId}`);
  215. if (error || !res?.success) {
  216. showAlert(error?.message || res?.message || "삭제에 실패했습니다.", "오류");
  217. } else {
  218. showAlert(res.message || "삭제되었습니다.", "성공");
  219. setTimeout(() => router.push("/site-manager/onboard/list"), 800);
  220. }
  221. },
  222. "선상 삭제"
  223. );
  224. };
  225. // 이동
  226. const goToList = () => router.push("/site-manager/onboard/list");
  227. const goToEdit = () => router.push(`/site-manager/onboard/edit/${onboardId}`);
  228. // 일시 포맷
  229. const formatDateTime = (dateString) => {
  230. if (!dateString) return "-";
  231. const date = new Date(dateString.replace(" ", "T"));
  232. if (isNaN(date.getTime())) return dateString;
  233. return date.toLocaleString("ko-KR", {
  234. year: "numeric",
  235. month: "2-digit",
  236. day: "2-digit",
  237. hour: "2-digit",
  238. minute: "2-digit",
  239. });
  240. };
  241. onMounted(() => {
  242. loadDetail();
  243. });
  244. </script>